#include <process.h>
#include <windows.h>
#include"Thread_Impl.h"
#include "CriticalSection.h"
Thread_Impl::Thread_Impl()
{
	m_poThrSection = new CCriticalSection;
}

Thread_Impl::~Thread_Impl()
{
	delete m_poThrSection;
}

unsigned __stdcall Thread_Impl::svc_run(void *apParam)
{
	unsigned ret = ((Thread_Impl *)apParam)->svc();
	{
		Thread_Impl *thisImpl = ((Thread_Impl *)apParam);
		CCriticalAutoLock loAutoLock(*(thisImpl->m_poThrSection));
		std::set<unsigned int>  &threads = thisImpl->h_threads;
		std::set<unsigned int>::iterator it = threads.find((unsigned int)GetCurrentThreadId());
		if (it != threads.end())
			threads.erase(it);
	}
    return ret;
}
int Thread_Impl::activate( int n_threads /*= 1*/ )
{
	CCriticalAutoLock loAutoLock(*m_poThrSection);

	if (!h_threads.empty())
		return -1;
    
	unsigned threadID;

    while (n_threads)
    {
        HANDLE hThreadRecv = (HANDLE)_beginthreadex(NULL, 0, &Thread_Impl::svc_run, (LPVOID)this, 0, &threadID);
        if (hThreadRecv)
        {
            h_threads.insert((unsigned int)threadID);
            CloseHandle(hThreadRecv);
        }
        n_threads--;
    }
    return h_threads.size();
}

int Thread_Impl::thr_count (void) const
{
	CCriticalAutoLock loAutoLock(*m_poThrSection);
    return h_threads.size();
}

void Thread_Impl::wait()
{
	int thr_num = 0;
	HANDLE *pHandleArray = NULL;
	while (true)
	{
		thr_num = 0;
		pHandleArray = NULL;
		{
			CCriticalAutoLock loAutoLock(*m_poThrSection);
            std::set<unsigned int>  temp_threads = h_threads;
            thr_num = temp_threads.size();
			pHandleArray = new HANDLE[thr_num];
			HANDLE *temp = pHandleArray;
            std::set<unsigned int>::iterator id_iterator = temp_threads.begin();

            while (id_iterator != temp_threads.end())
			{
				*temp = OpenThread(THREAD_ALL_ACCESS, FALSE, (DWORD)(*id_iterator));
				temp++;
                temp_threads.erase(id_iterator);
                id_iterator = temp_threads.begin();
			}
		}
		if (thr_num)
		{
			DWORD dwRet = WaitForMultipleObjects(thr_num, pHandleArray, TRUE, 100);

			for (int i = 0; i < thr_num; i++)
			{
				CloseHandle(pHandleArray[i]);
			}
			if (pHandleArray)
				delete[]pHandleArray;

			if ((dwRet != WAIT_TIMEOUT) && (dwRet != WAIT_FAILED))
				break;
		}
		else
		{
			break;
		}
	}
}
